package br.ufrj.dcc.so.entidades.barbeiros;

import java.sql.BatchUpdateException;
import java.util.concurrent.Semaphore;

import br.ufrj.dcc.so.entidades.clientes.Cliente;
import br.ufrj.dcc.so.entidades.clientes.EnumPatente;
import br.ufrj.dcc.so.forte.barbearia.Barbearia;
import br.ufrj.dcc.so.forte.barbearia.BarbeariaRecrutaZero;
import br.ufrj.dcc.so.forte.barbearia.Funcionario;

public abstract class BarbeiroAbstrato extends Funcionario{


	protected Barbearia barbearia;
	private Semaphore semaforoClientes;
	private Semaphore semaforoLugares;
	private static final Semaphore semaforoEscolheCliente = new Semaphore(1, true);
	
	public BarbeiroAbstrato(Barbearia barbearia, Semaphore semaforoLugares,	Semaphore semaforoClientes) {
		super(((BarbeariaRecrutaZero)barbearia).getInterfaceGrafica());
		
		this.semaforoLugares = semaforoLugares;
		this.semaforoClientes = semaforoClientes;

		this.barbearia = barbearia;
		
		
	}

	/**
	 * Método que atende um cliente.
	 */
	private void atendeCliente() {
		Cliente cliente = escolhaCliente();
		System.out.println("Cliente sendo atendido pelo barbeiro "+this.getClass().getSimpleName()+ "\t:"+cliente.getPatente().getPatente());
		interfaceGrafica.atendeCliente(cliente, this);
		sleep(cliente.getTempoServico());
	}

	/**
	 * Método que escolhe dentre as filas qual cliente será atendido!
	 * 
	 * @return Cliente a ser atendido
	 */
	protected Cliente escolhaCliente() {
		Cliente cliente = null;
		try {
			// Verifico se há algum produto produzido.
			semaforoClientes.acquire();

			semaforoEscolheCliente.acquire();
			cliente = barbearia.pegaProximoCliente(escolhePatente());
			semaforoEscolheCliente.release();

			// Indico que há espaço para a produção de pelo menos mais um
			// produto.
			semaforoLugares.release();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return cliente;

	}

	/**
	 * Método que escolhe a patente a ser atendida.
	 * 
	 * @return Patente a ser atendida
	 */
	protected abstract EnumPatente escolhePatente();

	/**
	 * Método que escolhe a patente de acordo com sua prioridades.
	 * 
	 * @return Patente a ser atendida
	 */
	protected abstract EnumPatente aplicaPrioridade();

	@Override
	public void run() {
		while (true) {
			atendeCliente();
		}
	}

}
